﻿using log4net;
using log4net.Repository;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data;
using System.Data.Common;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.Claims;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xml;
using Von.Library;
using Von.Web.Datas;
using Von.Web.Framework;
using Von.Web.Models;
using Von.Web.Structs;

// 系统调用及应用数据结构特点接口
namespace Von.Web.Interfaces
{
    #region 数据信息接口
    /// <summary>
    /// 需要初始化的接口
    /// </summary>
    public interface IInitiation
    {
        void init();
    }
    /// <summary>
    /// 支持任务类型
    /// </summary>
    public interface ITask
    {
        /// <summary>任务序号，与任务记录关联</summary>
        int TaskIdx { get; set; }
        /// <summary>任务摘要内容</summary>
        string Summary { get; set; }
        /// <summary>任务状态</summary>
        string Status { get; set; }
        /// <summary>待处理人，LoginName</summary>
        string Processor { get; set; }
        /// <summary>待处理角色，为空则为人处理</summary>
        string ProcessRole { get; set; }
    }
    /// <summary>
    /// 支持流程处理
    /// </summary>
    public interface IStatusInfo
    {
        /// <summary>流程序号</summary>
        Guid FlowIdx { get; set; }
        /// <summary>部门序号</summary>
        int DepartmentIdx { get; set; }
        /// <summary>任务状态</summary>
        string Status { get; set; }
        /// <summary>待处理人，LoginName</summary>
        string Processor { get; set; }
        /// <summary>待处理角色，为空则为人处理</summary>
        string ProcessRole { get; set; }
    }
    /// <summary>
    /// 审批流程处理记录
    /// </summary>
    public interface IStatusRecord
    {
        /// <summary>序号</summary>
        int ID { get; set; }
        /// <summary>原始状态</summary>
        string OrgStatus { get; set; }
        /// <summary>处理名称</summary>
        string Operation { get; set; }
        /// <summary>处理状态</summary>
        string Status { get; set; }
        /// <summary>发布人</summary>
        string Processor { get; set; }
        /// <summary>发布时间</summary>
        DateTime ProcessTime { get; set; }
    }
    /// <summary>
    /// 支持版本记录，每次修改会自动增加1
    /// </summary>
    public interface IVersion
    {
        int Version { get; set; }
    }
    /// <summary>
    /// 支持排序记录存储
    /// </summary>
    public interface IOrder
    {
        int DisplayOrder { get; set; }
    }
    /// <summary>
    /// 支持核押计算
    /// </summary>
    public interface ICRC
    {
        string CRCCode { get; set; }
        string CalcCRC { get; }
    }
    /// <summary>
    /// 支持树形结构
    /// </summary>
    public interface ITree<TKey>
    {
        TKey ID { get; set; }
        TKey PID { get; set; }
    }
    public interface ITreeChildren<T>
    {
        List<T> children { get; set; }
    }
    /// <summary>
    /// 支持Easyui树形结构展示结构
    /// </summary>
    public interface ITreeModel<TKey>
    {
        /// <summary>节点的 id，它对于加载远程数据很重要</summary>
        TKey id { get; set; }
        /// <summary>要显示的节点文本</summary>
        string text { get; set; }
        /// <summary>，'open' 或 'closed'，默认是 'open'。当设置为 'closed' 时，该节点有子节点，并且将从远程站点加载它们</summary>
        string state { get; }
        /// <summary>指示节点是否被选中</summary>
        bool Checked { get; set; }
        /// <summary>给一个节点添加的自定义属性</summary>
        string attributes { get; set; }
        //List<ITreeModel<TKey>> children { get; set; }
    }
    /// <summary>
    /// 支持编辑信息记录结构
    /// </summary>
    public interface IRecord
    {
        Guid Creator { get; set; }
        DateTime CreateTime { get; set; }
        Guid Modifier { get; set; }
        DateTime Modifidate { get; set; }
    }
    /// <summary>
    /// 支持历史记录
    /// </summary>
    public interface IHistory<TKey>
    {
        int HisID { get; set; }
        TKey ID { get; set; }
        int Version { get; set; }
    }
    /// <summary>
    /// 支持审批流程应用数据结构
    /// </summary>
    public interface StateFlowAppBase<key>
    {
        key ID { get; set; }
        string Status { get; set; }
        Guid Modifier { get; set; }
        DateTime Modifidate { get; set; }
        Guid NextChecker { get; set; }
        string NextRole { get; set; }
    }
#endregion
}
namespace Von.Web.Models
{
    /// <summary>
    /// 应用于程序集中的声明
    /// </summary>
    public abstract class AssemblyDefinationBase
    {
        /// <summary>
        /// 应用基本信息
        /// </summary>
        public abstract ApplicationDefinationBase AppDefination { get; }
        /// <summary>
        /// 应用需要引用的组件程序集集合
        /// </summary>
        public virtual string[] Imports { get => new string[0]; }
        /// <summary>
        /// 应用系统初始化信息
        /// </summary>
        public virtual bool Init() { return true; }
    }
    /// <summary>
    /// 应用声明基类
    /// </summary>
    public abstract class ApplicationDefinationBase : ApplicationModel
    {
        /// <summary>
        /// 读取配置内容
        /// </summary>
        /// <param name="json">配置内容（JSON类）</param>
        /// <param name="key">配置项目名称</param>
        /// <param name="defauleValue">默认值</param>
        /// <returns></returns>
        public JToken readJsonData(JObject json, string key, JToken defauleValue)
        {
            JToken obj = json[key];
            if (obj == null) return defauleValue; else return obj;
        }
        #region Definition of author
        /// <summary>版本信息</summary>
        public abstract int Version { get; }
        /// <summary>作者</summary>
        public abstract string Author { get; }
        /// <summary>版权说明</summary>
        public abstract string Copyright { get; }
        /// <summary>数据访问层命名空间</summary>
        public abstract string DBAccessNameSpacec { get; }
        /// <summary>资源文件名</summary>
        public string ResxName { get; }
        #endregion
        #region Effectiveness control
        /// <summary>应用是否有效判断</summary>
        public abstract bool CheckModuleAvailed(string ModuleName, Guid ActionIdx);
        #endregion
        #region Definition of database
        /// <summary>
        /// 数据库连接串
        /// </summary>
        public string DBConnectString { get; set; }
        /// <summary>
        /// 该应用中所包含的操作（包含页面、ajax接口等，所有包含Action特定的函数）集合
        /// </summary>
        public List<WebActionInfo> Actions { get; } = new List<WebActionInfo>();
        #endregion
        [JsonIgnore()]
        public abstract ApplicationDBAccessionBase DBAccession { get; }
        /// <summary>
        /// 数据访问层接口实例缓存
        /// </summary>
        [JsonIgnore()]
        private List<DBAccessBase> Accesses = new List<DBAccessBase>();
        /// <summary>
        /// 获取数据访问层实例，如果是无事务访问，则调用缓存，如果启动事务则创建新的实例
        /// </summary>
        /// <typeparam name="T">访问层实例</typeparam>
        /// <param name="trans">事务</param>
        /// <returns></returns>
        public T GetAccess<T>(DbTransaction trans = null) where T : DBAccessBase
        {
            string className = typeof(T).FullName.Insert(typeof(T).FullName.LastIndexOf('.') + 1, Prefix);
            string assemlyName = Prefix + AssemlyName + "DataAccess";
            if (trans == null)
            {
                DBAccessBase acc = Accesses.FirstOrDefault(a => a.GetType().FullName == className);
                if (acc == null)
                {
                    acc = (T)Reflection.CreateObject(assemlyName, className);
                    Accesses.Add(acc);
                    acc.DBTrans = null;
                }
                return (T)acc;
            }
            T access = (T)Reflection.CreateObject(assemlyName, className);
            access.DBTrans = trans;
            return access;
        }
    }
    /// <summary>
    /// Ajax远程调用接口参数
    /// </summary>
    public class JsonStr
    {
        /// <summary>
        /// 无参数构造函数
        /// </summary>
        public JsonStr() { }
        /// <summary>
        /// 含参数构造函数
        /// </summary>
        public JsonStr(string Data) { data = Data; }
        /// <summary>
        /// 数据
        /// </summary>
        public string data { get; set; }
        private JToken _jsonData = null;
        /// <summary>
        /// 获取Ajax调用的JSON数据
        /// </summary>
        public JObject Json
        {
            get
            {
                if (_jsonData == null)
                    _jsonData = (JToken)JsonConvert.DeserializeObject(data == null ? "" : data);
                return _jsonData as JObject;
            }
        }
        /// <summary>
        /// 获取Ajax调用的JArray数据
        /// </summary>
        public JArray Array
        {
            get
            {
                if (_jsonData == null)
                    _jsonData = (JToken)JsonConvert.DeserializeObject(data == null ? "" : data);
                return _jsonData as JArray;
            }
        }
        /// <summary>
        /// 获取json数据的值
        /// </summary>
        public static T JsonValue<T>(JToken j, T defaultValue)
        {
            if (j == null) return defaultValue;
            else return j.Value<T>();
        }
    }
    /// <summary>
    /// 查询条件
    /// </summary>
    public enum EDBCondition { 等于, 大于, 大于等于, 小于, 小于等于, 不等于, 前近似, 后近似, 前后近似, 在其中, 范围 }
    /// <summary>
    /// 条件间连接方式
    /// </summary>
    public enum DBConditionConnector { NONE, AND, OR }

    /// <summary>
    /// 数据访问时条件设置
    /// </summary>
    /// <example>
    /// A=2 AND (G>3 OR H=4)AND j=0 => {NONE,0,A,等于,2},{AND,1,G,大于,3},{OR,1,H,等于,4}{AND,0,j,等于,0}
    /// </example>
    public class DBCondition
    {
        public DBCondition() { }
        public DBCondition(DBConditionConnector Connector, int Level, string FieldName, EDBCondition Condition, object Data)
        {
            this.Connector = Connector;
            this.Level = Level;
            this.FieldName = FieldName;
            this.Condition = Condition;
            this.Data = Data;
        }
        public DBCondition(string FieldName, EDBCondition Condition, object Data)
        {
            this.FieldName = FieldName;
            this.Condition = Condition;
            this.Data = Data;
        }
        /// <summary>
        /// 条件间连接方式
        /// </summary>
        public DBConditionConnector Connector { get; set; } = DBConditionConnector.AND;
        /// <summary>
        /// 条件层级
        /// </summary>
        public int Level { get; set; } = 0;
        /// <summary>
        /// 键名称
        /// </summary>
        public string FieldName { get; set; }
        /// <summary>
        /// 条件符号
        /// </summary>
        public EDBCondition Condition { get; set; }
        /// <summary>
        /// 键值对象内容
        /// </summary>
        public object Data { get; set; }
    }
    /// <summary>
    /// 数据库查询内容设定
    /// </summary>
    public class DBSelection
    {
        /// <summary>
        /// 要查询的表名称
        /// </summary>
        public string TableCode { get; set; }
        /// <summary>
        /// 要查询的字段名称集合，以逗号间隔
        /// </summary>
        public string Fields { get; set; }
        /// <summary>
        /// 强制要关联的字段，在joins中设置有效
        /// </summary>
        public string refField { get; set; } = null;
        /// <summary>
        /// 强制要排序字段
        /// </summary>
        public string orderFields { get; set; } = null;
        /// <summary>
        /// 条件
        /// </summary>
        public DBCondition[] conditions { get; set; }
        /// <summary>
        /// 关联的表及字段信息，系统会根据系统数据库设置的关联信息进行关联
        /// </summary>
        public DBSelection[] Joins { get; set; } = null;
    }
    #region "Ajax 调用返回类型 ExecuteResult"
    public abstract class ExecuteResult
    {
        public abstract bool Successed { get; }
        /// <summary>
        /// Returns an <see cref="ExecuteResult"/> indicating a successful identity operation.
        /// </summary>
        /// <returns>An <see cref="ExecuteResult"/> indicating a successful operation.</returns>
        public static SuccessedResult Success(object obj)
        {
            var result = new SuccessedResult { Success = obj };
            return result;
        }
        public static SuccessedResult Success(object obj, params KeyValuePair<string, object>[] data)
        {
            Dictionary<string, object> datas = new Dictionary<string, object>();
            foreach (var d in data)
                datas.Add(d.Key, d.Value);
            var result = new SuccessedResult { Success = obj, Result = datas };
            return result;
        }
        [Obsolete("可以采用Success(object obj, params KeyValuePair<string , object>[] data)函数替代")]
        public static SuccessedResult Success(object obj, Dictionary<string, object> data)
        {
            var result = new SuccessedResult { Success = obj, Result = data };
            return result;
        }
        /// <summary>
        /// Creates an <see cref="ExecuteResult"/> indicating a failed identity operation, with a list of <paramref name="errors"/> if applicable.
        /// </summary>
        /// <param name="errors">An optional array of <see cref="ExecuteError"/>s which caused the operation to fail.</param>
        /// <returns>An <see cref="ExecuteResult"/> indicating a failed identity operation, with a list of <paramref name="errors"/> if applicable.</returns>
        public static FailedResult Failed(string resxFile, string Code, params object[] Description)
        {
            var result = new FailedResult { Error = Resource.GetResourceValue(resxFile, Code, Description) };
            return result;
        }
        public static FailedResult Failed(object errorInfo)
        {
            var result = new FailedResult { Error = errorInfo };
            return result;
        }
    }
    public class FailedResult : ExecuteResult
    {
        /// <summary>
        /// 错误信息内容
        /// </summary>
        public object Error { get; internal set; }
        /// <summary>
        /// 成功与否标记
        /// </summary>
        public override bool Successed => false;
    }
    public class SuccessedResult : ExecuteResult
    {
        /// <summary>
        /// 执行成功主要返回值
        /// </summary>
        public object Success { get; internal set; }
        /// <summary>
        /// 执行成功辅助返回值
        /// </summary>
        public object Result { get; internal set; }
        /// <summary>
        /// 成功与否标记
        /// </summary>
        public override bool Successed => true;
    }
    #endregion
    /// <summary>
    /// 树形结构节点移动位置描述=0：移动到目标位置下级最后位置；1：移动到目标位置上面；2：移动到目标位置下面
    /// </summary>
    public enum ETreeNodeMoveKind
    {
        /// <summary>
        /// 移动到目标节点的下级
        /// </summary>
        child = 0,
        /// <summary>
        /// 移动到目标节点的上面
        /// </summary>
        before = 1,
        /// <summary>
        /// 移动到目标节点的下面
        /// </summary>
        after = 2
    }
}
namespace Von.Web.Models
{
    /// <summary>
    /// 侦听回调处理事件
    /// </summary>
    /// <param name="App">应用名称</param>
    /// <param name="Cmd">待处理的命令</param>
    /// <param name="data">待处理的数据</param>
    /// <returns>如果处理完成，不再传递则返回true,否则为false，系统将消息传递给下一个侦听者</returns>
    public delegate Task<bool> EventOfListen(string App, string Cmd, JObject data);
    /// <summary>
    /// 侦听接口注册信息
    /// </summary>
    public class listener
    {
        /// <summary>
        /// 应用ID
        /// </summary>
        public Guid AppIdx { get; set; }
        /// <summary>
        /// 发送人信息（接收处理的唯一值）
        /// </summary>
        public string Sender { get; set; }
        /// <summary>
        /// 侦听事件
        /// </summary>
        public EventOfListen Event { get; set; }
    }
    /// <summary>
    /// 视图提示信息类型
    /// </summary>
    public enum EViewStatusClass { success, info, warning, danger }
    /// <summary>
    /// 日志级别类型
    /// </summary>
    public enum ELogLevel { debug, info, warning, danger }
    /// <summary>
    /// 控制器基类
    /// </summary>
    public abstract class WebControllerBase : Controller
    {
        private ILog _Log = null;
        /// <summary>
        /// 文件日志引擎
        /// </summary>
        public ILog Log
        {
            get
            {
                if (_Log == null)
                {
                    _Log = Runtime.CreateLog(this.GetType());
                }
                return _Log;
            }
        }
        /// <summary>
        /// 写入格式日志
        /// </summary>
        /// <param name="level">日志级别</param>
        /// <param name="process">进程名称</param>
        /// <param name="format">内容格式</param>
        /// <param name="args">格式参数</param>
        /// <returns></returns>
        public async Task WriteLogFormate(ELogLevel level, string process, string format, params object[] args)
        {
            await WriteLog(level, process, string.Format(format, args));
        }
        /// <summary>
        /// 写入日志内容
        /// </summary>
        /// <param name="level">日志级别</param>
        /// <param name="process">进程名称</param>
        /// <param name="content">日志内容</param>
        /// <returns></returns>
        public async Task WriteLog(ELogLevel level, string process, string content)
        {
            switch (level)
            {
                case ELogLevel.debug: Log.Debug(process + "==>" + content); break;
                case ELogLevel.info: Log.Info(process + "==>" + content); break;
                case ELogLevel.warning: Log.Warn(process + "==>" + content); break;
                case ELogLevel.danger: Log.Error(process + "==>" + content); break;
            }
            if ((int)level >= App.LogClass)
                await Runtime.LogTask.Add(new LogInfo() { LogTime = DateTime.Now, Level = (int)level, EventName = process, Content = content, Operator = (UserInfo == null ? "" : UserInfo.LoginName) });
        }
        /// <summary>
        /// 模块属性,建议使用静态变量储存
        /// </summary>
        public abstract ApplicationDefinationBase App { get; }
        private IdentityUserInfo _UserInfo = null;
        //public string UserLoginName{ get { return User.FindFirstValue(ClaimTypes.Name); } }
        //public string UserDisplayName { get { return User.FindFirstValue("DisplayName"); } }
        //public string UserEmail { get { return User.FindFirstValue(ClaimTypes.Email); } }
        //public string UserMobile { get { return User.FindFirstValue(ClaimTypes.MobilePhone); } }
        /// <summary>
        /// 获取当前用户信息
        /// </summary>
        /// <returns></returns>
        public IdentityUserInfo UserInfo
        {
            get
            {
                if (_UserInfo == null) //user = Runtime.GetIdentityUserInfo(UserID);
                {
                    var s = User.FindFirstValue(ClaimTypes.NameIdentifier);
                    if (string.IsNullOrEmpty(s)) return null;
                    Tasks.IdentityUserTask task = new Tasks.IdentityUserTask();
                    _UserInfo = task.GetByIdentity(Guid.Parse(s)).Result;
                }
                return _UserInfo;
            }
        }
        /// <summary>
        /// 设置本地cookie
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="value">值</param>  
        /// <param name="minutes">过期时长，单位：分钟</param>      
        protected void SetCookies(string key, string value, int minutes = 30)
        {
            HttpContext.Response.Cookies.Append(key, value, new Microsoft.AspNetCore.Http.CookieOptions
            {
                Expires = DateTime.Now.AddMinutes(minutes)
            });
        }
        /// <summary>
        /// 删除指定的cookie
        /// </summary>
        /// <param name="key">键</param>
        protected void DeleteCookies(string key)
        {
            HttpContext.Response.Cookies.Delete(key);
        }
        /// <summary>
        /// 获取cookies
        /// </summary>
        /// <param name="key">键</param>
        /// <returns>返回对应的值</returns>
        protected string GetCookies(string key)
        {
            HttpContext.Request.Cookies.TryGetValue(key, out string value);
            if (string.IsNullOrEmpty(value))
                value = string.Empty;
            return value;
        }
        /// <summary>
        /// 是否登录的标志
        /// </summary>
        /// <returns></returns>//User.Claims.Count() > 0;
        public bool IsLogin { get { return User.Identity.IsAuthenticated; } }
        /// <summary>
        /// Ajax出错后返回调用函数
        /// </summary>
        /// <param name="Code">错误编码</param>
        /// <param name="Description">错误参数</param>
        /// <returns></returns>
        public ExecuteResult Failed(string Code, params string[] Description)
        {
            FailedResult result = ExecuteResult.Failed(App.ResxName, Code, Description);
            WriteLog(ELogLevel.danger, "Execute", Code);
            return result;
        }
        public IActionResult ErrorView(string code, string errorMessage)
        {
            //return RedirectResult()
            return View("Error", new ErrorViewModel() { Code = code, ErrorMessage = errorMessage });
        }
        /// <summary>
        /// 页面出错后返回调用函数
        /// </summary>
        /// <param name="status">错误类型</param>
        /// <param name="info">错误信息</param>
        /// <param name="result">错误参数</param>
        /// <returns></returns>
        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult StatusView(EViewStatusClass status, string info, object result = null)
        {
            ViewBag.StateMessage = status.ToString() + ":" + info;
            return View(result);
        }
        /// <summary>
        /// 判断控制器使用权限
        /// </summary>
        /// <param name="context"></param>
        /// <param name="next"></param>
        /// <returns></returns>
        public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            if (App == null)
            {
                Runtime.Log.Error(App.AppName + "." + this.GetType().Name + " has not registed.");
                context.Result = new RedirectResult("/Account/Login");
                return;
            }
            else
            {
                MethodInfo method = ((ControllerActionDescriptor)context.ActionDescriptor).MethodInfo;
                foreach (object attribute in method.GetCustomAttributes(true)) //2.通过映射，找到成员属性上关联的特性类实例，
                {
                    if (attribute is ActionAttribute)//3.如果找到了限定长度的特性类对象，就用这个特性类对象验证该成员
                    {
                        if (!App.CheckModuleAvailed(this.GetType().Name, ((ActionAttribute)attribute).ID))
                        {
                            Runtime.Log.Error(App.AppName + "." + this.GetType().Name + " check certification failed.");
                            return;
                        }
                        if (!await Runtime.checkRight(User, ((ActionAttribute)attribute).ID))
                        {
                            Log.WarnFormat("User %s 无权限使用 %s，转入登录界面", UserInfo == null ? "Guest" : UserInfo.LoginName, ((ActionAttribute)attribute).ID.ToString());
                            HttpContext.Response.Cookies.Append("vonportal_login_error", "overdue");
                            context.Result = new RedirectResult("/Account/Login?returnUrl=" + context.HttpContext.Request.Path);
                            return;
                        }
                    }
                }
            }
            try
            {
                await base.OnActionExecutionAsync(context, next);
            }
            catch (Exception e)
            {
                Log.FatalFormat("App=%s, Model=%s，异常=%s", App.AppName, this.GetType().Name, e.Message);
            }
        }
    }
    /// <summary>
    /// 模块功能 信息类
    /// </summary>
    public class WebActionInfo
    {
        #region "Constructors"
        /// <summary>
        /// 构造函数
        /// </summary>
        public WebActionInfo()
        {
        }
        /// <summary>
        /// 含初始化构造函数
        /// </summary>
        /// <param name="ID">唯一标识</param>
        /// <param name="ActionName">功能名称</param>
        /// <param name="Description">功能说明</param>
        /// <param name="ControlKind">控制类型</param>
        public WebActionInfo(Guid ID, string ModuleName, string Area, string Controller, string ActionName, string Description, EControlKind ControlKind)
        {
            this.ID = ID;
            this.ModuleName = ModuleName;
            this.Area = Area;
            this.Controller = Controller;
            this.ActionName = ActionName;
            this.Description = Description;
            this.ControlKind = ControlKind;
        }
        #endregion
        #region "Public Properties"
        /// <summary>模块名称</summary>
        public string ModuleName { get; set; }
        /// <summary>序号</summary>
        public Guid ID { get; set; }
        /// <summary>区域名称</summary>
        public string Area { get; set; }
        /// <summary>控制名称</summary>
        public string Controller { get; set; }
        /// <summary>功能名称集</summary>
        public string ActionName { get; set; }
        /// <summary>功能描述</summary>
        public string Description { get; set; }
        /// <summary>控制类型</summary>
        public EControlKind ControlKind { get; set; }
        #endregion
    }
    /// <summary>
    /// 系统服务时间间隔单位
    /// </summary>
    public enum ServiceInterKind { 毫秒, 秒, 分, 时, 日, 周, 月, 年 }
    /// <summary>系统服务 信息类</summary>
    [ErrorHandle]
    public abstract class WebServiceBase
    {
        #region "Public Properties"
        /// <summary>序号</summary>
        [Required]
        [LocalDisplay("序号", "系统服务")]
        public Guid ID { get; set; }
        /// <summary>服务名称</summary>
        [LocalDisplay("服务名称", "系统服务")]
        public string ServiceName { get; set; }
        /// <summary>间隔方式</summary>
        [LocalDisplay("间隔方式", "系统服务")]
        public ServiceInterKind InterKind { get; set; }
        private int _Intervalue = 1000;
        /// <summary>间隔值</summary>
        [LocalDisplay("间隔值", "系统服务")]
        public int Intervalue
        {
            get { return _Intervalue; }
            set
            {
                _Intervalue = value;
                if (nextTime.Equals(DateTime.MinValue)) nextTime = DateTime.Now;
                nextTime = GetNextTime();
            }
        }
        /// <summary>必要性</summary>
        [LocalDisplay("必要性", "系统服务")]
        public bool Necessary { get; set; }
        /// <summary>状态</summary>
        [LocalDisplay("状态", "系统服务")]
        public string Status { get; set; }
        /// <summary>运行参数</summary>
        [LocalDisplay("运行参数", "系统服务")]
        public string Param {
            get { return Newtonsoft.Json.JsonConvert.SerializeObject(JsonParam); }
            set { JsonParam = string.IsNullOrEmpty(value) ? JObject.Parse("{}") : JObject.Parse(value); }
        }
        public Newtonsoft.Json.Linq.JObject JsonParam = null;
        /// <summary>
        /// 读取配置内容
        /// </summary>
        /// <param name="json">配置内容（JSON类）</param>
        /// <param name="key">配置项目名称</param>
        /// <param name="defauleValue">默认值</param>
        /// <returns></returns>
        public JToken ParamData(string key, JToken defauleValue)
        {
            JToken obj = JsonParam[key];
            if (obj == null) return defauleValue; else return obj;
        }
        #endregion
        public ApplicationDefinationBase App { get; set; }
        /// <summary>下一个任务执行时间</summary>
        public DateTime nextTime { get; set; }
        public DateTime GetNextTime()
        {
            switch (InterKind)
            {
                case ServiceInterKind.毫秒:
                    if (Necessary) return nextTime.AddMilliseconds(Intervalue);
                    else return DateTime.Now.AddMilliseconds(Intervalue);
                case ServiceInterKind.秒:
                    if (Necessary) return nextTime.AddSeconds(Intervalue);
                    else return DateTime.Now.AddSeconds(Intervalue);
                case ServiceInterKind.分:
                    if (Necessary) return nextTime.AddMinutes(Intervalue);
                    else return DateTime.Now.AddMinutes(Intervalue);
                case ServiceInterKind.时:
                    if (Necessary) return nextTime.AddHours(Intervalue);
                    else return DateTime.Now.AddHours(Intervalue);
                case ServiceInterKind.日:
                    if (Necessary) return nextTime.AddDays(Intervalue);
                    else return DateTime.Now.AddDays(Intervalue);
                case ServiceInterKind.周:
                    if (Necessary) return nextTime.AddDays(Intervalue * 7);
                    else return DateTime.Now.AddDays(Intervalue * 7);
                case ServiceInterKind.月:
                    if (Necessary) return nextTime.AddMonths(Intervalue);
                    else return DateTime.Now.AddMonths(Intervalue);
                case ServiceInterKind.年:
                    if (Necessary) return nextTime.AddYears(Intervalue);
                    else return DateTime.Now.AddYears(Intervalue);
                default: return DateTime.Now;
            }
        }
        public bool IsBusy { get; protected set; }
        public abstract Task Run();
    }
    /// <summary>大屏显示模块基类(ScreenComponentBase)</summary>
    public abstract class ScreenComponentBase
    {
        #region "Properties"
        /// <summary>组件名称</summary>
        public abstract string ComponentName { get; }
        /// <summary>效果图</summary>
        public abstract string Sketch { get; }
        /// <summary>参数结构</summary>
        public abstract JObject ParamSchema { get; }
        /// <summary>作者</summary>
        public abstract string Author { get; }
        /// <summary>版本</summary>
        public abstract string Version { get; }
        /// <summary>宽度</summary>
        public abstract int Width { get; }
        /// <summary>高度</summary>
        public abstract int Height { get; }
        /// <summary>发布日期</summary>
        public abstract DateTime Publishedate { get; }
        /// <summary>版权声明</summary>
        public abstract string Copyright { get; }
        public virtual string Design(ScreenItemModel item)
        {
            return "<div id='SCREEN_" + item.ID.ToString() + "' class='easyui-draggable' data-options='onDrag:onDrag' style='" + item.Style + "'></div>";
        }
        public abstract string Run(ScreenItemModel item);
        #endregion
    }
    public delegate object GetData(Dictionary<string, object> data);
    /// <summary>
    /// 短信平台的接口基类
    /// </summary>
    public abstract class SMSBase
    {
        public static SMSBase GetSMSInstance(string ServiceName)
        {
            JObject SMSSetting = (JObject)Statement.App.AppSetting["SmsSetting"];
            string InstanceAssembly = SMSSetting[ServiceName].ToString();
            Von.Web.Framework.Runtime.Log.Debug("Will to create sms instance with " + InstanceAssembly);
            if (string.IsNullOrEmpty(InstanceAssembly)) return null;
            SMSBase result = (SMSBase)Von.Web.Framework.Reflection.CreateObject(InstanceAssembly);
            return result;
        }
        protected Dictionary<string, JObject> providers = new Dictionary<string, JObject>();
        public void RegistProvider(string providerName, string setting)
        {
            var provider = providers.FirstOrDefault(p => p.Key.Equals(providerName, StringComparison.OrdinalIgnoreCase));
            if (default(KeyValuePair<string, JObject>).Equals(provider)) providers.Add(providerName, JObject.Parse(setting));
            else providers[providerName] = JObject.Parse(setting);
        }
        protected Dictionary<string, string> formats = new Dictionary<string, string>();
        public void RegistFormat(string formatName, string content)
        {
            var provider = formats.FirstOrDefault(p => p.Key.Equals(formatName, StringComparison.OrdinalIgnoreCase));
            if (default(KeyValuePair<string, JObject>).Equals(provider)) formats.Add(formatName, content);
            else formats[formatName] = content;
        }
        public abstract Task<bool> SingleSend(string providerName, string mobile, string content);
        public abstract Task<bool> BatchSend(string providerName, string[] mobiles, string[] contents);
        public Task SingleFormatSend(string providerName, string formatName, string mobile, Dictionary<string, object> data)
        {
            string content = formats[formatName];
            return SingleSend(providerName, mobile, Von.Library.Functions.VonFormat(formats[formatName], data));
        }
        public Task BatchFormatSend(string providerName, GetData getFormatName, GetData getMobile, List<Dictionary<string, object>> data)
        {
            List<string> mobiles = new List<string>();
            List<string> contents = new List<string>();
            foreach (var d in data)
            {
                mobiles.Add(getMobile(d).ToString());
                contents.Add(Von.Library.Functions.VonFormat(formats[getFormatName(d).ToString()], d));
            }
            return BatchSend(providerName, mobiles.ToArray(), contents.ToArray());
        }
    }
    /// <summary>
    /// 我的任务设定参数信息
    /// </summary>
    public class MyTaskSetting
    {
        public string TaskName { get; set; }
        public string TaskGroup { get; set; }
        public ApplicationDefinationBase App { get; set; }
        public DBSelection Selection { get; set; }
        public string TitleFmt { get; set; }
        public string UrlFmt { get; set; }
    }
    /// <summary>
    /// 我的任务信息
    /// </summary>
    public class MyTaskInfo
    {
        public string TaskName { get; set; }
        public string Title { get; set; }
        public string Url { get; set; }
    }
}
namespace Von.Web.Datas
{
    /// <summary>
    /// 表间链接信息
    /// </summary>
    public class VonTableReference
    {
        /// <summary>
        /// 源字段
        /// </summary>
        public string srcField { get; set; }
        /// <summary>
        /// 引用目标表
        /// </summary>
        public string destTable { get; set; }
        /// <summary>
        /// 引用目标对应字段
        /// </summary>
        public string destField { get; set; }
    }
    /// <summary>
    /// 表字段信息
    /// </summary>
    public class VonDefinationField
    {
        /// <summary>
        /// 字段名称
        /// </summary>
        public string fieldCode { get; set; }
        /// <summary>
        /// 字段说明
        /// </summary>
        public string fieldName { get; set; }
        /// <summary>
        /// 字段数据类型
        /// </summary>
        public int fieldType { get; set; }
    }
    /// <summary>
    /// 系统表信息
    /// </summary>
    public class VonTableDefination
    {
        /// <summary>
        /// 表字段集合
        /// </summary>
        public VonDefinationField[] Fields = null;
        /// <summary>
        /// 表字引用字段集合
        /// </summary>
        public VonTableReference[] Reference = null;
        /// <summary>
        /// 字段名称
        /// </summary>
        public string tableName = "";
        /// <summary>
        /// 字段说明
        /// </summary>
        public string tableCode = "";
        /// <summary>
        /// 主键
        /// </summary>
        public string keyField = "";
        /// <summary>
        /// 父联字段，如果没有为空
        /// </summary>
        public string parentField = "";
        /// <summary>
        /// 支持排序的字段名，如果没有为空
        /// </summary>
        public string orderField = "";
    }
    /// <summary>
    /// 应用数据库访问器基类
    /// </summary>
    public abstract class ApplicationDBAccessionBase
    {
        /// <summary>
        /// 本应用中所包含的表结构信息
        /// </summary>
        public abstract VonTableDefination[] tables { get; }
        /// <summary>
        /// 创建数据库连接
        /// </summary>
        public abstract IDbConnection CreateConnection();
        /// <summary>
        /// 开启一个数据库事务
        /// </summary>
        public abstract IDbTransaction BeginDBTrans();
        /// <summary>
        /// 创建SQL语句执行单元
        /// </summary>
        public abstract DbCommand InitCommand(string sqlText, DbTransaction DBTrans);
        /// <summary>
        /// 应用
        /// </summary>
        public abstract ApplicationDefinationBase AppDefination { get; set; }
        /// <summary>
        /// 获取数据库支持的字段类型
        /// </summary>
        /// <returns></returns>
        public abstract Dictionary<string, int> DBTypes {get; }
        /// <summary>
        /// 读取数据库表中内容
        /// </summary>
        /// <param name="SQL">查询的SQL语句</param>
        /// <param name="Param">键值对的参数设置</param>
        /// <returns></returns>
        public abstract Dictionary<string, object> GetFromDB(string SQL, Dictionary<string, object> Param = null);
        /// <summary>
        /// 读取数据库表中内容
        /// </summary>
        /// <param name="SQL">查询的SQL语句</param>
        /// <param name="Param">键值对的参数设置</param>
        /// <returns></returns>
        public abstract Dictionary<string, object> GetFromDB(string SQL, JObject Param = null);
        /// <summary>
        /// 读取数据库表中内容
        /// </summary>
        /// <param name="selection">要选择的内容，selection={TableCode:TableCode,Fields:[Field...],Joins:[selection...]}</param>
        /// <param name="conditions">要选择的条件设置，conditions=[condition...]，condition={Connector:NONE|AND|OR,Level=Level,FieldName=FieldName,Condition=Condition,Data=Data}</param>
        /// <returns></returns>
        public abstract Dictionary<string, object> GetFromDB(JObject selection);
        /// <summary>
        /// 读取数据库表中内容
        /// </summary>
        /// <param name="selection">要选择的内容，selection={TableCode:TableCode,Fields:[Field...],Joins:[selection...]}</param>
        /// <param name="conditions">要选择的条件设置，conditions=[condition...]，condition={Connector:NONE|AND|OR,Level=Level,FieldName=FieldName,Condition=Condition,Data=Data}</param>
        /// <returns></returns>
        public abstract Dictionary<string, object> GetFromDB(DBSelection selection);
        /// <summary>
        /// 读取数据库表中内容
        /// </summary>
        /// <param name="SQL">查询的SQL语句</param>
        /// <param name="Param">键值对的参数设置</param>
        /// <returns></returns>
        public abstract List<Dictionary<string, object>> ListFromDB(string SQL, Dictionary<string, object> Param = null);
        /// <summary>
        /// 读取数据库表中内容
        /// </summary>
        /// <param name="SQL">查询的SQL语句</param>
        /// <param name="Param">键值对的参数设置</param>
        /// <returns></returns>
        public abstract List<Dictionary<string, object>> ListFromDB(string SQL, JObject Param = null);
        /// <summary>
        /// 读取数据库表中内容
        /// </summary>
        /// <param name="selection">要选择的内容，selection={TableCode:TableCode,Fields:[Field...],Joins:[selection...]}</param>
        /// <param name="conditions">要选择的条件设置，conditions=[condition...]，condition={Connector:NONE|AND|OR,Level=Level,FieldName=FieldName,Condition=Condition,Data=Data}</param>
        /// <returns></returns>
        public abstract List<Dictionary<string, object>> ListFromDB(JObject selection);
        /// <summary>
        /// 读取数据库表中内容
        /// </summary>
        /// <param name="selection">要选择的内容，selection={TableCode:TableCode,Fields:[Field...],Joins:[selection...]}</param>
        /// <param name="conditions">要选择的条件设置，conditions=[condition...]，condition={Connector:NONE|AND|OR,Level=Level,FieldName=FieldName,Condition=Condition,Data=Data}</param>
        /// <returns></returns>
        public abstract List<Dictionary<string, object>> ListFromDB(DBSelection selection);
    }
    /// <summary>
    /// 应用数据库访问器基类
    /// </summary>
    public abstract class StatementDBAccessionBase: ApplicationDBAccessionBase
    {
        /// <summary>
        /// 树形结构移动位置
        /// </summary>
        /// <param name="tableCode">表名称</param>
        /// <param name="key">主键值</param>
        /// <param name="newPID">新位置的父节点值</param
        /// <param name="newOrder">新的排序位置值</param>
        /// <returns></returns>
        public abstract bool TreeMove<T>(string tableCode, T key, T newPID, int newOrder, DbTransaction trans = null);
        /// <summary>
        /// 插入表数据
        /// </summary>
        /// <param name="tableCode">表名称</param>
        /// <param name="values">字段内容列表</param>
        /// <param name="trans">事务</param>
        /// <returns>是否成功</returns>
        public abstract bool InsertToDB(string tableCode, Dictionary<string, object> values, DbTransaction trans = null);
        /// <summary>
        /// 插入表数据
        /// </summary>
        /// <param name="tableCode">表名称</param>
        /// <param name="values">字段内容列表</param>
        /// <param name="trans">事务</param>
        /// <returns>是否成功</returns>
        public abstract bool InsertToDB(string tableCode, JObject values, DbTransaction trans = null);
        /// <summary>
        /// 插入后，返回键值
        /// </summary>
        /// <param name="tableCode">表名称</param>
        /// <param name="values">字段内容列表</param>
        /// <param name="trans">事务</param>
        /// <returns>返回插入的主键</returns>
        public abstract object InsertIdentity(string tableCode, Dictionary<string, object> values, DbTransaction trans = null);
        /// <summary>
        /// 插入后，返回键值
        /// </summary>
        /// <param name="tableCode">表名称</param>
        /// <param name="values">字段内容列表</param>
        /// <param name="trans">事务</param>
        /// <returns>返回插入的主键</returns>
        public abstract object InsertIdentity(string tableCode, JObject values, DbTransaction trans = null);
        /// <summary>
        /// 更新数据表字段内容
        /// </summary>
        /// <param name="tableCode">表名称</param>
        /// <param name="values">字段内容列表</param>
        /// <param name="trans">事务</param>
        /// <returns>是否成功</returns>
        public abstract bool UpdateToDB(string tableCode, Dictionary<string, object> values, DbTransaction trans = null);
        /// <summary>
        /// 更新数据表字段内容
        /// </summary>
        /// <param name="tableCode">表名称</param>
        /// <param name="values">字段内容列表</param>
        /// <param name="trans">事务</param>
        /// <returns>是否成功</returns>
        public abstract bool UpdateToDB(string tableCode, JObject values, DbTransaction trans = null);
        /// <summary>
        /// 删除数据表内容
        /// </summary>
        /// <param name="tableCode">表名称</param>
        /// <param name="keyValue">主键值</param>
        /// <param name="trans">事务</param>
        /// <returns>是否成功</returns>
        public abstract bool DeleteFromDB(string tableCode, object keyValue, DbTransaction trans = null);
        /// <summary>
        /// 根据条件删除数据表内容
        /// </summary>
        /// <param name="tableCode">表名称</param>
        /// <param name="values">删除条件集合</param>
        /// <param name="trans">事务</param>
        /// <returns>是否成功</returns>
        public abstract bool DeleteByCondition(string tableCode, Dictionary<string, object> values, DbTransaction trans = null);
        /// <summary>
        /// 根据条件删除数据表内容
        /// </summary>
        /// <param name="tableCode">表名称</param>
        /// <param name="values">删除条件集合</param>
        /// <param name="trans">事务</param>
        /// <returns>是否成功</returns>
        public abstract bool DeleteByCondition(string tableCode, JObject values, DbTransaction trans = null);
        ///// <summary>
        ///// 更新数据库中指定表信息
        ///// </summary>
        ///// <param name="TableCode">表名称</param>
        ///// <param name="values">更新值列表</param>
        ///// <param name="key">关键字段，将作为Where语句进行定位</param>
        ///// <param name="DBTransTrans">事务句柄，默认无</param>
        ///// <returns></returns>
        //public abstract int Update(string TableCode, KeyObjectCollection values, KeyObject key, DbTransaction DBTransTrans = null);
        ///// <summary>
        ///// 综合查询
        ///// </summary>
        ///// <param name="Sql">查询语句</param>
        ///// <param name="Condition">条件</param>
        ///// <param name="OrderFields">排序字段列表</param>
        ///// <returns></returns>
        //public abstract IDataReader Search(string Sql, List<DBCondition> Condition, string[] OrderFields = null);
    }
    public abstract class DBAccessBase
    {
        public delegate void EventAddParameter(string key, object val);

        public string HistoryQualifier = "";
        public DbTransaction DBTrans { get; set; }
        public static byte[] ReadImage(IDataReader reader, int Idx)
        {
            byte[] data = new byte[256];
            using (MemoryStream ms = new MemoryStream())
            {
                long fieldOffset = 0;
                long len = 0;
                do
                {
                    len = reader.GetBytes(Idx, fieldOffset, data, 0, 256);
                    ms.Write(data, 0, (int)len);
                    fieldOffset += len;
                } while (len == 256);
                ms.Position = 0;
                byte[] result = new byte[ms.Length];
                ms.Read(result, 0, (int)ms.Length);
                ms.Close();
                return result;
            }
        }
        #region 根据设置条件生成WHERE语句
        private static string getConditionSql(string varName, string varValue, string fmt, EventAddParameter addParameter)
        {
            string fld = varName.TrimEnd(new char[10]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'});
            addParameter(varName, varValue);
            return string.Format(fmt, fld, varName);
        }
        private static string getSearchSql(string key, string value, EventAddParameter addParameter)
        {
            string lnk = " AND ";
            if (key.StartsWith('_'))
            {
                lnk = " OR  ";
                key = key.Substring(1);
            }
            if (key.EndsWith('0'))
            {
                return lnk + getConditionSql(key, value.ToString(), "{0}=@{1}", addParameter);
            }
            else if (key.EndsWith('1'))
            {
                return lnk + getConditionSql(key, value.ToString(), "{0}>=@{1}", addParameter);
            }
            else if (key.EndsWith('2'))
            {
                return lnk + getConditionSql(key, value.ToString(), "{0}<@{1}", addParameter);
            }
            else if (key.EndsWith('3'))
            {
                return lnk + getConditionSql(key, value.ToString(), "{0} LIKE @{1}+'%'", addParameter);
            }
            else if (key.EndsWith('4'))
            {
                return lnk + getConditionSql(key, value.ToString(), "{0} LIKE '%'+@{1}+'%'", addParameter);
            }
            else if (key.EndsWith('5'))
            {
                return lnk + getConditionSql(key, value.ToString(), "{0} LIKE '%'+@{1}", addParameter);
            }
            else if (key.EndsWith('6'))
            {
                return lnk + getConditionSql(key, value.ToString(), "{0}<=@{1}", addParameter);
            }
            else if (key.EndsWith('7'))
            {
                return lnk + getConditionSql(key, value.ToString(), "{0}>@{1}", addParameter);
            }
            else if (key.EndsWith('8'))
            {
                return lnk + getConditionSql(key, value.ToString(), "{0}<>@{1}", addParameter);
            }
            else if (key.EndsWith('9'))
            {
                return lnk + getConditionSql(key, value.ToString(), "{0} IN (@{1})", addParameter);
            }
            else
            {
                return " AND " + getConditionSql(key, value.ToString(),"{0}=@{1}", addParameter);
            }
        }
        public static string GereralSearchSql(Dictionary<string, object> ConditionData, EventAddParameter addParameter)
        {
            string sqlWhere = "";
            foreach (KeyValuePair<string, object> jp in ConditionData)
            {
                if (jp.Value is Dictionary<string, object>)
                    sqlWhere += (jp.Key.StartsWith('_') ? " OR  (" : " AND (") + GereralSearchSql((Dictionary<string, object>)jp.Value, addParameter) + ")";
                else if (string.IsNullOrEmpty(jp.Value.ToString())) continue;
                else sqlWhere += getSearchSql(jp.Key, jp.Value.ToString(), addParameter);
            }
            return sqlWhere;
        }
        public static string GereralSearchSql(JObject ConditionJson, EventAddParameter addParameter)
        {
            string sqlWhere = "";
            foreach (JProperty jp in ConditionJson.Properties())
            {
                if (jp.Value is JObject)
                    sqlWhere += (jp.Name.StartsWith('_') ? " OR  (" : " AND (") + GereralSearchSql((JObject)jp.Value, addParameter) + ")";
                else if (string.IsNullOrEmpty(jp.Value.ToString())) continue;
                else sqlWhere += getSearchSql(jp.Name, jp.Value.ToString(), addParameter);
            }
            return sqlWhere == "" ? "" : sqlWhere.Substring(5);
        }
        #endregion
        /// <summary>只检查SQL语法，不执行SQL语句。</summary>
        /// <param name="cmd">DbCommand控件</param>
        /// <param name="sql">SQL语句</param>
        /// <returns></returns>
        public static string ValidateSQL(DbCommand cmd, string sql)
        {
            string result;
            cmd.CommandText = "SET PARSEONLY ON";
            cmd.ExecuteNonQuery();
            try
            {
                cmd.CommandText = sql;
                cmd.ExecuteNonQuery();
                result = "";
            }
            catch (Exception ex)
            {
                result = ex.Message;
            }
            cmd.CommandText = "SET PARSEONLY OFF";
            cmd.ExecuteNonQuery();
            return result;
        }
    }
}
namespace Von.Web.Tasks
{
    public class TaskCreation
    {
        internal ApplicationDefinationBase module;
        public TaskBase GetTask(DbTransaction trans = null)
        {
            return null;
        }
    }
    public abstract class TaskBase
    {
        public DBAccessBase dbAccess;
        protected DbTransaction DBTrans = null;
    }
}